Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn for is-pattern using a relational pattern with a known result. #42501

Merged

Conversation

gafter
Copy link
Member

@gafter gafter commented Mar 17, 2020

Relates to #40727 (patterns for C# 9)

@gafter gafter added this to the Compiler.Net5 milestone Mar 17, 2020
@gafter gafter requested review from agocke and RikkiGibson March 17, 2020 17:48
@gafter gafter requested a review from a team as a code owner March 17, 2020 17:48
@gafter gafter self-assigned this Mar 17, 2020
@gafter gafter force-pushed the patterns3-is-always-true-false branch from 47db30f to 7d4d669 Compare March 20, 2020 18:02
@gafter
Copy link
Member Author

gafter commented Mar 20, 2020

@agocke @RikkiGibson Can you please review this small pattern-matching change?

else if (values?.Complement().IsEmpty != true)
{
tests.Add(new Tests.One(new BoundDagRelationalTest(rel.Syntax, rel.Relation, rel.ConstantValue, output, rel.HasErrors)));
}
Copy link
Member

@cston cston Mar 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider wrapping block in if (fac is { }) { ... } to avoid multiple ?. operators and == true. #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that, but ended up having to repeat line 625 in multiple else clauses.


In reply to: 395854215 [](ancestors = 395854215)

case BoundDagRelationalTest d:
var f = ValueSetFactory.ForSpecialType(input.Type.SpecialType);
if (f is null) return null;
// TODO: When ValueSetFactory has a method for comparing two values, use it.
Copy link
Member

@cston cston Mar 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO [](start = 31, length = 4)

PROTOTYPE? #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The code works correctly as is. This is a suggestion for a future optimization, which I expect to happen after merging into master.


In reply to: 395854439 [](ancestors = 395854439)

Copy link
Member

@jcouv jcouv Mar 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be also filed as a follow-up issue? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wouldn't be particularly helpful to me, though I don't object to it.


In reply to: 397252372 [](ancestors = 397252372)

}
";
CreateCompilation(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.RegularWithPatternCombinators).VerifyDiagnostics(
// (7,18): error CS8120: The switch case has already been handled by a previous case.
Copy link
Member

@cston cston Mar 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error CS8120: The switch case has already been handled by a previous case. [](start = 31, length = 74)

This diagnostic message is confusing since there is no previous case. #Resolved

Copy link
Member Author

@gafter gafter Mar 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what to do about this, as this is the message used (since C# 7.0) when a switch case is unreachable. What do you suggest? Give a different message if it is the first case? Reword it to be technically correct "Any value that would match this case has been handled by a previous case." ?


In reply to: 395883716 [](ancestors = 395883716)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or perhaps "Unreachable case. If there are values that satisfy this case, those values have been handled in previous cases."


In reply to: 395908208 [](ancestors = 395908208,395883716)

// (7,18): error CS8120: The switch case has already been handled by a previous case.
// case < int.MinValue: break; // 1
Diagnostic(ErrorCode.ERR_SwitchCaseSubsumed, "< int.MinValue").WithLocation(7, 18),
// (9,18): error CS8120: The switch case has already been handled by a previous case.
Copy link
Member

@cston cston Mar 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error CS8120: The switch case has already been handled by a previous case. [](start = 31, length = 74)

This message is confusing since the previous cases do not handle this (out of range) case. #Resolved

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks (iteration 4)

@jcouv jcouv self-assigned this Mar 24, 2020
@gafter
Copy link
Member Author

gafter commented Mar 24, 2020

@cston Do these error messages look better?

@gafter gafter closed this Mar 24, 2020
@gafter gafter reopened this Mar 24, 2020
@gafter
Copy link
Member Author

gafter commented Mar 25, 2020

@cston @jcouv @agocke @RikkiGibson Would you please have a look at the last iteration of this PR? It now gives warnings for more scenarios of always-true is-pattern expressions as requested at the feature design review yesterday.

@@ -1231,6 +1231,9 @@ void M4(int* p)
// (6,29): error CS8521: Pattern-matching is not permitted for pointer types.
// bool M1(int* p) => p is null; // 1
Diagnostic(ErrorCode.ERR_PointerTypeInPatternMatching, "null").WithLocation(6, 29),
// (7,24): warning CS8794: An expression of type 'int*' always matches the provided pattern.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should/could we try and avoid the cascade here? The error (not pattern-matching on pointer type) seems more fundamental

@@ -354,9 +354,16 @@ void Test2(object x)
");
c.VerifyTypes();
c.VerifyDiagnostics(
// (6,13): warning CS8794: An expression of type 'object' always matches the provided pattern.
// if (x is var _)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be added to the breaking changes document and thread.

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks (iteration 8), modulo documentation of breaking change (such as warning on var _)

@gafter
Copy link
Member Author

gafter commented Mar 25, 2020

@jcouv I removed the breaking change.

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Thanks (iteration 9)

@gafter gafter merged commit 7fcd921 into dotnet:features/patterns3 Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants